package top.malegod.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.malegod.mapper.OrderMapper;
import top.malegod.model.Alipay;
import top.malegod.service.AlipayService;
import top.malegod.utils.AlipayConfig;
import top.malegod.utils.LogFile;

import java.util.Map;

/**
 * Create by IntelliJ IDEA
 *
 * @author: AbelEthan
 * @date-Time: 2018/5/24 21:33
 * @description: 支付宝实现service接口
 */
@Service
public class AlipayServiceImpl implements AlipayService {

    private final String TRADE_STATUS_FINISHED = "TRADE_FINISHED";

    private final String TRADE_STATUS_SUCCESS = "TRADE_SUCCESS";

   @Autowired
   private OrderMapper orderMapper;

    @Override
    public String close(String outTradeNo, String tradeNo) throws AlipayApiException {

        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID,
                AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        AlipayTradeCloseRequest alipayRequest = new AlipayTradeCloseRequest();

        AlipayTradeCloseModel model = new AlipayTradeCloseModel();
        model.setOutTradeNo(outTradeNo);
        model.setTradeNo(tradeNo);
        alipayRequest.setBizModel(model);

        AlipayTradeCloseResponse alipayResponse = client.execute(alipayRequest);

        return alipayResponse.getBody();
    }

    @Override
    public String downloadUrl(String billType, String billDate) throws AlipayApiException {

        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID,
                AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        AlipayDataDataserviceBillDownloadurlQueryRequest alipayRequest = new AlipayDataDataserviceBillDownloadurlQueryRequest();

        AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel();
        model.setBillType(billType);
        model.setBillDate(billDate);
        alipayRequest.setBizModel(model);

        AlipayDataDataserviceBillDownloadurlQueryResponse alipayResponse = client.execute(alipayRequest);
        return alipayResponse.getBillDownloadUrl();
    }

    @Override
    public String pay(Alipay alipay) throws AlipayApiException {

        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID,
                AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();


        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(alipay.getWIDout_trade_no());
        model.setSubject(alipay.getWIDsubject());
        model.setTotalAmount(alipay.getWIDtotal_amount());
        model.setBody(alipay.getWIDbody());
        model.setTimeoutExpress(alipay.getTimeOutEcpress());
        model.setProductCode(alipay.getProductCode());
        alipayRequest.setBizModel(model);
        // 设置异步通知地址
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
        // 设置同步地址
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        // 调用SDK生成表单
        String form = client.pageExecute(alipayRequest).getBody();
        return form;
    }

    @Override
    public String query(String outTradeNo, String tradeNo) throws AlipayApiException {
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID,
                AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();

        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        model.setOutTradeNo(outTradeNo);
        model.setTradeNo(tradeNo);
        alipayRequest.setBizModel(model);

        AlipayTradeQueryResponse alipayResponse = client.execute(alipayRequest);
        return alipayResponse.getBody();
    }

    @Override
    public String refund(Alipay alipay) throws AlipayApiException {
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID,
                AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();

        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(alipay.getWIDout_trade_no());
        model.setTradeNo(alipay.getWIDtrade_no());
        model.setRefundAmount(alipay.getWIDrefund_reason());
        model.setRefundReason(alipay.getWIDrefund_reason());
        model.setOutRequestNo(alipay.getWIDout_request_no());
        alipayRequest.setBizModel(model);

        AlipayTradeRefundResponse alipayResponse = client.execute(alipayRequest);
        return alipayResponse.getBody();
    }

    @Override
    public String refundQuery(Alipay alipay) throws AlipayApiException {
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID,
                AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        AlipayTradeFastpayRefundQueryRequest alipayRequest = new AlipayTradeFastpayRefundQueryRequest();

        AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
        model.setOutTradeNo(alipay.getWIDout_trade_no());
        model.setTradeNo(alipay.getWIDtrade_no());
        model.setOutRequestNo(alipay.getWIDout_request_no());
        alipayRequest.setBizModel(model);

        AlipayTradeFastpayRefundQueryResponse alipayResponse = client.execute(alipayRequest);
        return alipayResponse.getBody();
    }

    @Override
    public void returnUrl(Map<String, String> params) throws AlipayApiException {
        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        //商户订单号
        String orderId = params.get("out_trade_no");
        //支付宝交易号
        String trade_no = params.get("trade_no");
        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        //计算得出通知验证结果
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        boolean  verifyResult = AlipaySignature
                .rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2");
        //验证成功
        LogFile.logResult("return");
        if (verifyResult) {


            //////////////////////////////////////////////////////////////////////////////////////////
            //请在这里加上商户的业务逻辑程序代码
            //该页面可做页面美工编辑
            //out.clear();
            //out.println("验证成功<br />");
            //——请根据您的业务逻辑来编写程序（以上代码仅作参考）——
            for (Object o : params.keySet()) {
                System.out.println("key=" + o + " value=" + params.get(o));
                LogFile.logResult("key = " + o + "——value =" + params.get(o));
            }

            //////////////////////////////////////////////////////////////////////////////////////////
        } else {
            //该页面可做页面美工编辑
            //out.clear();
            //out.println("验证失败");
            System.out.println("no success");
        }
    }

    @Override
    public String notifyUrl(Map<String, String> params, String tradeStatus) throws AlipayApiException {
        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        //商户订单号
        String orderId = params.get("out_trade_no");
        //支付宝交易号
        String trade_no = params.get("trade_no");
        //交易状态

        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        //计算得出通知验证结果
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        boolean verifyResult = AlipaySignature
                .rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2");
        //验证成功
        if (verifyResult) {
            //////////////////////////////////////////////////////////////////////////////////////////
            //请在这里加上商户的业务逻辑程序代码

            //——请根据您的业务逻辑来编写程序（以下代码仅作参考）——

            if (tradeStatus.equals(TRADE_STATUS_FINISHED)) {
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                //如果有做过处理，不执行商户的业务程序
                for (Object o : params.keySet()) {
                    System.out.println("key=" + o + " value=" + params.get(o));
                    LogFile.logResult("key = " + o + "——value =" + params.get(o));
                }
                return "error";
                //注意：
                //如果签约的是可退款协议，退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
                //如果没有签约可退款协议，那么付款完成后，支付宝系统发送该交易状态通知。
            } else if (tradeStatus.equals(TRADE_STATUS_SUCCESS)) {
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                //如果有做过处理，不执行商户的业务程序
                LogFile.logResult("notify");
                for (Object o : params.keySet()) {
                    System.out.println("key=" + o + " value=" + params.get(o));
                    LogFile.logResult("key = " + o + "——value =" + params.get(o));
                }
                orderMapper.payOrder(orderId);
                //注意：
                //如果签约的是可退款协议，那么付款完成后，支付宝系统发送该交易状态通知。
            }

            //——请根据您的业务逻辑来编写程序（以上代码仅作参考）——
            //out.clear();
            //out.println("success");	//请不要修改或删除
            return "success";
            //////////////////////////////////////////////////////////////////////////////////////////
        } else {//验证失败
            //out.println("fail");
            return "error";
        }
    }
}